﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;

namespace UseEntityJig
{
    public class DrawLineDynamicDimensionJig
    {
        /// <summary>
        /// 拖动鼠标画矩形，并标注动态文本长度
        /// </summary>
        [CommandMethod("DrawLineDynamicDimension")]
        public void DrawLineDynamicDimension()
        {
            Document Doc = Application.DocumentManager.MdiActiveDocument;
            Editor Ed = Doc.Editor;

            PromptPointResult pointRes = Ed.GetPoint(new PromptPointOptions("请输入一个点:\n"));
            if (pointRes.Status != PromptStatus.OK) return;

            Line line = new Line() { StartPoint = pointRes.Value };
            // 测量沿直线的两点之间的距离，而不考虑该线的方向（水平、垂直或任何角度）
            AlignedDimension dim = new AlignedDimension() { XLine1Point = line.StartPoint, DimensionStyle = ObjectId.Null };

            JigPromptPointOptions jigOpts = new JigPromptPointOptions();
            jigOpts.BasePoint = pointRes.Value;
            jigOpts.UseBasePoint = true;
            // 创建自定义Jig实例
            MyJig myJig = new MyJig();

            myJig.PromptInput(jigOpts, "输入第二个点");
            myJig.JigEnts.Add(line);
            myJig.JigEnts.Add(dim);
            myJig.SetJigUpdate((jig) =>
            {
                line.EndPoint = jig.Point;
                dim.XLine2Point = jig.Point;
                dim.DimensionText = line.Length.ToString();

                var centerPt = new Point3d(
                    (line.StartPoint.X + jig.Point.X) / 2,
                    (line.StartPoint.Y + jig.Point.Y) / 2,
                    (line.StartPoint.Z + jig.Point.Z) / 2
                );
                //指定尺寸线的位置
                dim.DimLinePoint = centerPt + (jig.Point - line.StartPoint).GetNormal().RotateBy(Math.PI / 2, Vector3d.ZAxis) * 5;// Reduced from 10 to 5

            });

            if (myJig.Drag() != PromptStatus.OK)
            {
                return;
            }

            AddEntitiesToModelSpace(Doc, myJig.JigEnts);
        }

        private void AddEntitiesToModelSpace(Document doc, List<Entity> entities)
        {
            using (var tr = doc.Database.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead);
                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

                foreach (var ent in entities)
                {
                    btr.AppendEntity(ent);
                    tr.AddNewlyCreatedDBObject(ent, true);
                }

                tr.Commit();
            }
        }
    }

    public class MyJig : DrawJig
    {
        public Point3d Point = Point3d.Origin;
        Func<JigPrompts, SamplerStatus> InputFunc;
        public List<Entity> JigEnts = new List<Entity>();
        Action<MyJig> JigUpdateAction;

        public MyJig()
        {
            JigEnts.Clear();
            InputFunc = null;
        }

        public void SetJigUpdate(Action<MyJig> action)
        {
            JigUpdateAction = action;
        }

        public void PromptInput(JigPromptPointOptions pointOpts, string msg)
        {
            InputFunc = (prmpts) =>
            {
                pointOpts.Message = msg;
                var res = prmpts.AcquirePoint(pointOpts);
                if (res.Value == Point)
                {
                    return SamplerStatus.NoChange;
                }
                else if (res.Value != Point)
                {
                    Point = res.Value;
                    return SamplerStatus.OK;
                }
                else
                {
                    return SamplerStatus.Cancel;
                }
            };
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            if (InputFunc == null)
            {
                return SamplerStatus.NoChange;
            }

            return InputFunc.Invoke(prompts);
        }

        /// <summary>
        /// 把更新数据后的实体实时的绘制到屏幕上去
        /// </summary>
        /// <param name="draw"></param>
        /// <returns></returns>
        protected override bool WorldDraw(WorldDraw draw)
        {
            if (JigEnts.Count > 0)
            {
                //这是个委托，主要实现如何去更新实体
                JigUpdateAction(this);
                foreach (var ent in JigEnts)
                {
                    ent.WorldDraw(draw);
                }
            }
            return true;
        }

        public PromptStatus Drag()
        {
            return Application.DocumentManager.MdiActiveDocument.Editor.Drag(this).Status;
        }
    }
}

